package cn.wen.yaling.xo.service.impl;

import cn.wen.yaling.commons.constant.RedisConstants;
import cn.wen.yaling.commons.entity.*;
import cn.wen.yaling.commons.enums.CommentStatus;
import cn.wen.yaling.commons.enums.CommentType;
import cn.wen.yaling.commons.service.RedisService;
import cn.wen.yaling.commons.vo.CommentChildVO;
import cn.wen.yaling.commons.vo.CommentListVO;
import cn.wen.yaling.commons.vo.CommentVO;
import cn.wen.yaling.xo.dao.WebConfigDao;
import cn.wen.yaling.xo.service.ImageService;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.wen.yaling.commons.utils.PageUtils;
import cn.wen.yaling.commons.utils.Query;

import cn.wen.yaling.xo.dao.CommentDao;
import cn.wen.yaling.xo.service.CommentService;
import org.springframework.transaction.annotation.Transactional;


@Service("commentService")
public class CommentServiceImpl extends ServiceImpl<CommentDao, CommentEntity> implements CommentService {

    @Autowired
    private CommentDao commentDao;

    @Autowired
    private ImageService imageService;

    @Autowired
    private WebConfigDao webConfigDao;

    @Autowired
    private RedisService redisService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CommentEntity> page = this.page(
                new Query<CommentEntity>().getPage(params),
                new QueryWrapper<CommentEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public Long getCommentNumByArticleId(Integer articleId) {
        QueryWrapper<CommentEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("article_id", articleId);
        Long count = commentDao.selectCount(queryWrapper);
        return count;
    }

    @Override
    public Long getCommentTotalNum() {
        // 评论状态为正常使用
        QueryWrapper<CommentEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("comment_status", 1);
        return commentDao.selectCount(queryWrapper);
    }

    @Override
    public List<CommentVO> listCommentByArticleId(Integer articleId) {
        // 获取楼主的数据，通过评论时间来排列
        List<CommentVO> comments = commentDao.findByArticleIdAdnParentCommentNull(articleId);
        optimizeComment(comments);
        return eachComment(comments);
    }

    @Transactional
    @Override
    public boolean insertComment(CommentEntity commentEntity) {
        // 通过articleId获取 当前userId 的邮箱
        if (commentEntity.getArticleId() != null) {
            UserEntity userEntity = commentDao.getUserByArticleId(commentEntity.getArticleId());
            System.out.println(userEntity);
            if (commentEntity.getCommentEmail().equals(userEntity.getUserEmail())) {
                commentEntity.setIsArticler(true);
            } else {
                commentEntity.setIsArticler(false);
            }
        } else if (commentEntity.getQuestionsId() != null) {
            // 需要获取当前问答的信息 判断是否为本人
            QuestionsEntity questionsEntity = commentDao.getQuestionsByQuestionId(commentEntity.getQuestionsId());
            System.out.println(questionsEntity);
            if (commentEntity.getCommentEmail().equals(questionsEntity.getQuestionEmail())) {
                commentEntity.setIsArticler(true);
            } else {
                commentEntity.setIsArticler(false);
            }
        } else if (commentEntity.getQuestionsId() == null && commentEntity.getArticleId() == null) {
            // 需要获取当前系统的信息 判断是否为本人
            QueryWrapper<WebConfigEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("status", 1);
            WebConfigEntity webConfigInfo = webConfigDao.selectList(queryWrapper).get(0);
            if (commentEntity.getCommentEmail().equals(webConfigInfo.getAuthorEmail())) {
                commentEntity.setIsArticler(true);
            } else {
                commentEntity.setIsArticler(false);
            }
        }
        commentEntity.setCommentStatus(1);
        commentEntity.setUpdateTime(new Date());
        commentEntity.setCreateTime(new Date());
        // 获取数据库中评论头像的列表  然后随机
        List<ImageEntity> commentAvatars = imageService.getCommentAvatarList();
        commentEntity.setCommentAvatar(commentAvatars.get(RandomUtils.nextInt(0,commentAvatars.size())).getImageUrl());
        int insert = commentDao.insert(commentEntity);
        return insert > 0;
    }

    @Override
    public List<CommentVO> getAboutCommentList() {
        // 获取楼主的数据，通过评论时间来排列
        List<CommentVO> comments = commentDao.findAboutCommentAndParentNull();
        optimizeComment(comments);
        return eachComment(comments);
    }

    @Override
    public void updateArticleViewsNum(Integer articleId) {

    }

    @Override
    public Long getCommentNumByQuestionId(Integer questionId) {
        QueryWrapper<CommentEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("questions_id", questionId);
        Long count = commentDao.selectCount(queryWrapper);
        return count;
    }

    @Override
    public List<CommentVO> listCommentByQuestionId(Integer questionId) {
        // 获取楼主的数据，通过评论时间来排列
        List<CommentVO> comments = commentDao.findQuestionCommentAndParentNull(questionId);
        optimizeComment(comments);
        return eachComment(comments);
    }

    @Override
    public Long getAboutCommentCount() {
        QueryWrapper<CommentEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("comment_type", CommentType.ABOUT_COMMENT.getType());
        queryWrapper.eq("comment_status", CommentStatus.PUBLISHED.getStatus());
        return commentDao.selectCount(queryWrapper);
    }

    @Override
    public List<CommentListVO> getCommentListByType(Integer type) {
        QueryWrapper<CommentEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("comment_type", type);
        queryWrapper.eq("parent_comment_id", 0);
        queryWrapper.ne("comment_status", CommentStatus.DELETED.getStatus());
        List<CommentEntity> commentList = commentDao.selectList(queryWrapper);
        return commentList.stream().map((item) -> {
            CommentListVO target = new CommentListVO();
            BeanUtils.copyProperties(item, target);
            return target;
        }).collect(Collectors.toList());
    }

    @Override
    public List<CommentChildVO> getChildCommentList(Integer parentId) {
        CommentChildVO parentComment = getParentComment(parentId);
        //获取二级评论
        parentComment.replyComments = commentDao.listTreeChileComment(parentId);
        List<CommentChildVO> parentComments = new ArrayList<>();
        parentComments.add(parentComment);
        List<CommentChildVO> commentParams = eachChildComment(parentComments);
        if (commentParams.size() > 0) {
            return commentParams.get(0).getReplyComments();
        }
        return new ArrayList<>();
    }

    @Override
    public boolean deleteCommentByIds(List<Integer> commentIds) {
        return commentDao.updateByIds(commentIds, CommentStatus.DELETED.getStatus());
    }

    @Override
    public boolean updateCommentStatusById(Integer commentId, Integer status) {
        CommentEntity target = new CommentEntity();
        target.setCommentId(commentId);
        target.setCommentStatus(status);
        boolean res= commentDao.updateById(target) > 0;
        // 需要删除评论缓存
        if (res) {
            if (redisService.hasKey(RedisConstants.CACHE_COMMENT_LIST)) {
                redisService.del(RedisConstants.CACHE_COMMENT_LIST);
            }
        }
        return res;
    }

    @Override
    public Long getCommentCountByStatus(int status) {
        QueryWrapper<CommentEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("comment_status", status);
        return commentDao.selectCount(queryWrapper);
    }

    @Override
    public List<CommentListVO> searchCommentListByType(Integer type, String keyword) {
        QueryWrapper<CommentEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("comment_type", type);
        queryWrapper.eq("parent_comment_id", 0);
        queryWrapper.ne("comment_status", CommentStatus.DELETED.getStatus());
        queryWrapper.like("comment_context", keyword);
        List<CommentEntity> commentList = commentDao.selectList(queryWrapper);
        return commentList.stream().map((item) -> {
            CommentListVO target = new CommentListVO();
            BeanUtils.copyProperties(item, target);
            return target;
        }).collect(Collectors.toList());
    }

    /**
     * 通过 父评论来获取该评论的信息
     * @param parentId
     * @return
     */
    private CommentChildVO getParentComment(Integer parentId) {
        CommentEntity commentEntity = commentDao.selectById(parentId);
        CommentChildVO target = new CommentChildVO();
        BeanUtils.copyProperties(commentEntity, target);
        return target;
    }


    private void optimizeComment(List<CommentVO> comments) {
        for (CommentVO comment : comments) {
            comment.setInOpen(false);
            comment.setReplyComments(commentDao.listTreeComment(comment.getCommentId()));
        }
    }


    /**
     * 循环每个顶级的评论节点
     *
     * @param comments
     * @return
     */
    private List<CommentVO> eachComment(List<CommentVO> comments) {
        List<CommentVO> commentsView = new ArrayList<>();
        for (CommentVO comment : comments) {
            CommentVO c = new CommentVO();
            BeanUtils.copyProperties(comment, c);
            // 存储全部的楼主评论
            commentsView.add(c);
        }
        // 合并评论的各层子代到第一级子代集合中
        combineChildren(commentsView);
        return commentsView;
    }

    //存放迭代找出的所有子代的集合
    private List<CommentVO> tempReply = new ArrayList<>();

    /**
     * @param comments root根节点，blog不为空的对象集合
     * @return
     */
    private void combineChildren(List<CommentVO> comments) {
        for (CommentVO comment : comments) {
            // 获取子列表
            List<CommentVO> replyComments = comment.getReplyComments();
            for (CommentVO replyComment : replyComments) {
                // 循环迭代，找出只子代，将子代存储到当前的二级列表中
                recursively(replyComment);
            }
            // 修改顶级的子节点设置处理过后的数据
            comment.setReplyComments(tempReply);
            // 清空暂存区
            tempReply = new ArrayList<>();
        }
    }

    /**
     * 递归迭代，剥洋葱
     *
     * @param comment 被迭代的对象
     * @return
     */
    private void recursively(CommentVO comment) {
        beanCopyProperties(comment);
        // 然后判断是否还有子评论 如果存在回复 则再次的调用递归
        if (comment.getReplyComments().size() > 0) {
            List<CommentVO> replyComments = comment.getReplyComments();
            for (CommentVO replyComment : replyComments) {
                beanCopyProperties(replyComment);
                if (replyComment.getReplyComments().size() > 0) {
                    recursively(replyComment);
                }
            }
        }
    }
    private void beanCopyProperties(CommentVO comment) {
        CommentVO commentOne = new CommentVO();
        BeanUtils.copyProperties(comment, commentOne);
        commentOne.setReplyComments(null);
        // 先将该子回复添加到列表中
        tempReply.add(commentOne);
    }

    /**
     * 循环每个顶级的评论节点
     *
     * @param comments
     * @return
     */
    private List<CommentChildVO> eachChildComment(List<CommentChildVO> comments) {
        List<CommentChildVO> commentsView = new ArrayList<>();
        for (CommentChildVO comment : comments) {
            CommentChildVO c = new CommentChildVO();
            BeanUtils.copyProperties(comment, c);
            // 存储全部的楼主评论
            commentsView.add(c);
        }
        // 合并评论的各层子代到第一级子代集合中
        combineChildrenComment(commentsView);
        return commentsView;
    }

    //存放迭代找出的所有子代的集合
    private List<CommentChildVO> tempChildReply = new ArrayList<>();

    /**
     * @param comments root根节点，blog不为空的对象集合
     * @return
     */
    private void combineChildrenComment(List<CommentChildVO> comments) {
        for (CommentChildVO comment : comments) {
            // 获取子列表
            List<CommentChildVO> replyComments = comment.getReplyComments();
            for (CommentChildVO replyComment : replyComments) {
                // 循环迭代，找出只子代，将子代存储到当前的二级列表中
                recursivelyChild(replyComment);
            }
            // 修改顶级的子节点设置处理过后的数据
            comment.setReplyComments(tempChildReply);
            // 清空暂存区
            tempChildReply = new ArrayList<>();
        }
    }

    /**
     * 递归迭代，剥洋葱
     *
     * @param comment 被迭代的对象
     * @return
     */
    private void recursivelyChild(CommentChildVO comment) {
        beanChildCopyProperties(comment);
        // 然后判断是否还有子评论 如果存在回复 则再次的调用递归
        if (comment.getReplyComments().size() > 0) {
            List<CommentChildVO> replyComments = comment.getReplyComments();
            for (CommentChildVO replyComment : replyComments) {
                beanChildCopyProperties(replyComment);
                if (replyComment.getReplyComments().size() > 0) {
                    recursivelyChild(replyComment);
                }
            }
        }
    }
    private void beanChildCopyProperties(CommentChildVO comment) {
        CommentChildVO commentOne = new CommentChildVO();
        BeanUtils.copyProperties(comment, commentOne);
        commentOne.setReplyComments(null);
        // 先将该子回复添加到列表中
        tempChildReply.add(commentOne);
    }
}